#!/usr/bin/env python
# -*- coding:utf-8 -*-


import re
import logging
import socket
import json
import traceback
import datetime
import time

try:
    from collections import OrderedDict
except ImportError:
    pass


RESERVED_ATTRS = (
    'args', 'asctime', 'created', 'exc_info', 'exc_text', 'filename',
    'funcName', 'levelname', 'levelno', 'lineno', 'module',
    'msecs', 'message', 'msg', 'name', 'pathname', 'process',
    'processName', 'relativeCreated', 'stack_info', 'thread', 'threadName')


RESERVED_ATTR_HASH = dict(zip(RESERVED_ATTRS, RESERVED_ATTRS))

COLORS ={
    'HEADER' : '\033[95m',
    'INFO' : '\033[94m',
    'DEBUG' : '\033[92m',
    'WARNING' : '\033[93m',
    'ERROR' : '\033[91m',
    'ENDC' : '\033[0m',
}

def merge_record_extra(record, target, reserved=RESERVED_ATTR_HASH):
    for key, value in record.__dict__.items():
        if (key not in reserved
            and not (hasattr(key, "startswith")
                     and key.startswith('_'))):
            target[key] = value
    return target

def get_host_info():
    host_name = ''
    local_ip = ''
    try:
        host_name = socket.gethostname()
        local_ip = socket.gethostbyname(host_name)
    except Exception, e:
        pass

    return host_name, local_ip

class JsonFormatterBase(logging.Formatter):

    def __init__(self,  *args, **kwargs):

        logging.Formatter.__init__(self, *args, **kwargs)
        self._required_fields = self.parse()
        self._skip_fields = dict(zip(self._required_fields,self._required_fields))
        self._skip_fields.update(RESERVED_ATTR_HASH)
    def parse(self):
        standard_formatters = re.compile(r'\((.+?)\)', re.IGNORECASE)
        return standard_formatters.findall(self._fmt)


    def add_fields(self, record ):
        log_record = {}

        for field in self._required_fields:
            log_record[field] = record.__dict__.get(field)

        host_name , local_ip = get_host_info()

        log_record[u'@hostName'] = host_name
        log_record[u'@localIp'] = local_ip
        return log_record

        #merge_record_extra(record, log_record, reserved=self._skip_fields)


    def process_log_record(self, log_record):
        """
        Override this method to implement custom logic
        on the possibly ordered dictionary.
        """

        try:
            new_record = OrderedDict()
        except Exception, e:
            return log_record

        key_list = [
            'asctime',
            'levelname',
            '@hostName',
            '@localIp',
            'threadName',
            'thread',
            'name',
            'pathname',
            'lineno',
            'message',
        ]
        for k in key_list:
            new_record[k] = log_record.get(k)
        new_record.update(log_record)
        return new_record

    def jsonify_log_record(self, log_record):
        """Returns a json string of the log record."""

        return json.dumps(log_record, ensure_ascii=False)


    def format_col(self, message_str, level_name):
        """

        是否需要颜色
        """
        return  message_str

    def formatTime(self, record, datefmt=None):
        ct = self.converter(record.created)
        if datefmt:
            s = time.strftime(datefmt, ct)
        else:
            t = time.strftime("%Y-%m-%d %H:%M:%S", ct)
            s = "%s.%03d" % (t, record.msecs)
        return s

    def format(self, record):


        if isinstance(record.msg, dict):
            record.message = record.msg

        elif isinstance(record.msg, list) or isinstance(record.msg, tuple):
            record.message = record.msg

        elif isinstance(record.msg, basestring):
            record.message = record.getMessage().split('\n')

        elif isinstance(record.msg, Exception):
            record.message = traceback.format_exc(record.msg).split('\n')

        else :
            record.message = repr(record.msg)

        if "asctime" in self._required_fields:
            record.asctime = self.formatTime(record, self.datefmt)

        #
        # if record.exc_info and not message_dict.get('exc_info'):
        #     message_dict['message'] = traceback.format_exception(*record.exc_info)
        log_record = self.add_fields(record)
        log_record = self.process_log_record(log_record)
        message_str  = self.jsonify_log_record(log_record)
        message_str = self.format_col(message_str, level_name=record.levelname)
        return message_str



class ConsoleFormater(JsonFormatterBase):

    def __init__(self, *args, **kwargs):
        JsonFormatterBase.__init__(self, *args, **kwargs)

    def format_col(self, message_str, level_name):
        if level_name in COLORS.keys():
            message_str = COLORS.get(level_name) + message_str + COLORS.get('ENDC')
        return message_str

    def jsonify_log_record(self, log_record):
        return json.dumps(log_record, ensure_ascii=False, indent=4)


class JsonFileFormater(JsonFormatterBase):

    def __init__(self, *args, **kewars):
        JsonFormatterBase.__init__(self, *args, **kewars)

    def jsonify_log_record(self, log_record):
        return json.dumps(log_record, ensure_ascii=False)
